package com.zian.service.impl;



import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zian.context.BaseContext;
import com.zian.domain.dto.*;
import com.zian.domain.po.*;
import com.zian.domain.query.OrderQuery;
import com.zian.domain.vo.OrderDetailsVO;
import com.zian.domain.vo.ShoppingQueryVO;
import com.zian.enums.IsDeletedEnum;
import com.zian.enums.OrderStatusEnum;
import com.zian.enums.PayStatusEnum;
import com.zian.enums.PayTypeEnum;
import com.zian.exception.BizIllegalException;
import com.zian.exception.DbException;
import com.zian.mapper.SysOrderMapper;
import com.zian.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zian.utils.IdUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since 2024-09-08
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SysOrderServiceImpl extends ServiceImpl<SysOrderMapper, SysOrder> implements ISysOrderService {

    private final ISysShoppingCartItemService shoppingCartItemService;

    private final ISysOrderItemService orderItemService;

    private final ISysOrderAddressService orderAddressService;

    private final ISysUserAddressService userAddressService;

    private final ISysGoodsInfoService goodsInfoService;

    private final IPayService payService;



    /**
     * 统计各个订单状态的数据
     *
     * @return
     */
    @Override
    public List<OrderStatusDTO> statisticsOrderCount() {
        QueryWrapper<SysOrder> qw = new QueryWrapper<>();
        qw.select("order_status as orderStatus","count(*) as count");
        qw.groupBy("order_status");
        List<Map<String, Object>> maps = this.listMaps(qw);
        List<OrderStatusDTO> dtos = new ArrayList<>();
        for (Map<String, Object> map : maps) {
            OrderStatusDTO orderStatusDTO = new OrderStatusDTO();
            orderStatusDTO.setOrderStatus(Integer.parseInt(map.get("orderStatus").toString()));
            orderStatusDTO.setCount(Long.parseLong(map.get("count").toString()));
            dtos.add(orderStatusDTO);
        }
        return dtos;
    }

    @Override
    public SysOrder getByOrderNo(String orderNo) {
        SysOrder order = lambdaQuery().eq(SysOrder::getOrderNo, orderNo).one();
        if (order == null) throw new BizIllegalException("订单不存在");
        return order;
    }

    /**
     * 查询当前用户的订单信息
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<OrderDetailsVO> queryCurUserOrderList(OrderQuery query) {
        Long currentId = BaseContext.getCurrentId();

        // 1. 先查询用户的订单
        Page<SysOrder> page = query.toMpPageDefaultSortByCreateTimeDesc();
        List<Integer> oderStatusList = getOrderIds(query);
        lambdaQuery()
                .eq(SysOrder::getUserId, currentId)
                .in(oderStatusList != null, SysOrder::getOrderStatus, oderStatusList)
                .page(page);
        List<SysOrder> orderList = page.getRecords();
        if (CollUtil.isEmpty(orderList)) return PageDTO.empty(0L, 0L);

        // 2. 根据订单id查询订单详情
        List<Long> orderIds = orderList.stream().map(SysOrder::getId).collect(Collectors.toList());
        List<SysOrderItem> orderItemList = orderItemService.lambdaQuery()
                .in(SysOrderItem::getOrderId, orderIds)
                .list();
        if (CollUtil.isEmpty(orderItemList)) throw new BizIllegalException("订单详情为空");
        Map<Long, List<SysOrderItem>> orderItemMap = orderItemList.stream().collect(Collectors.groupingBy(SysOrderItem::getOrderId));
        List<OrderDetailsVO> orderDetailsVOS = BeanUtil.copyToList(orderList, OrderDetailsVO.class);
        for (OrderDetailsVO orderDetailsVO : orderDetailsVOS) {
            orderDetailsVO.setOrderItemList(orderItemMap.get(orderDetailsVO.getId()));
        }

        return PageDTO.of(page, orderDetailsVOS);
    }

    /**
     * 获取指定状态的订单id集合
     * @param query
     * @return
     */
    private static List<Integer> getOrderIds(OrderQuery query) {
        List<Integer> orderStatusList = new ArrayList<>();
        if (query.getOrderStatus() == null || query.getOrderStatus() == 100) {
            orderStatusList = null;
        } else if (query.getOrderStatus() == 200) {
            orderStatusList.add(OrderStatusEnum.MANUAL_CLOSED.getCode());
            orderStatusList.add(OrderStatusEnum.TIMEOUT_CLOSED.getCode());
            orderStatusList.add(OrderStatusEnum.MERCHANT_CLOSED.getCode());
        } else {
            orderStatusList.add(query.getOrderStatus());
        }
        return orderStatusList;
    }

    /**
     * 订单完成
     * @param id
     */
    @Override
    public void completeOrder(Long id) {
        Long currentId = BaseContext.getCurrentId();
        SysOrder order = getById(id);
        if (order == null) throw new BizIllegalException("订单不存在");
        if (!order.getUserId().equals(currentId)) throw new BizIllegalException("只能确定自己的订单");
        if (!order.getOrderStatus().equals(OrderStatusEnum.GOODS_DELIVERED)) {
            log.error("订单状态异常 订单状为：{} 导致无法确认 ", order.getOrderStatus().getDescription());
            throw new BizIllegalException("订单状态异常");
        }


        boolean b = lambdaUpdate()
                .eq(SysOrder::getId, order.getId())
                .set(SysOrder::getOrderStatus, OrderStatusEnum.TRANSACTION_SUCCESS)
                .set(SysOrder::getUpdateTime, LocalDateTime.now())
                .update();
        if (!b) throw new DbException("订单完成失败");

    }

    /**
     * 取消订单
     * @param dto
     * @param isAdmin
     */
    @Override
    public void cancelOrder(OrderCancelDTO dto, boolean isAdmin) {
        Long currentId = BaseContext.getCurrentId();
        SysOrder order = getById(dto.getId());
        if (order == null) throw new BizIllegalException("订单不存在");

        if (isAdmin) {
            // 已支付 、配货完成、出库成功  （商家关闭）
            if (!(order.getOrderStatus().equals(OrderStatusEnum.PAID)
                    || order.getOrderStatus().equals(OrderStatusEnum.GOODS_ALLOCATED)
                    || order.getOrderStatus().equals(OrderStatusEnum.GOODS_DELIVERED))) {
                throw new BizIllegalException("订单状态异常");
            }
        } else {
            if (!order.getUserId().equals(currentId)) throw new BizIllegalException("只能确定自己的订单");
            // 已支付 、配货完成、 出库成功 、待支付 （用户关闭）
            if (!(order.getOrderStatus().equals(OrderStatusEnum.PAID)
                    || order.getOrderStatus().equals(OrderStatusEnum.GOODS_ALLOCATED)
                    || order.getOrderStatus().equals(OrderStatusEnum.GOODS_DELIVERED)
                    || order.getOrderStatus().equals(OrderStatusEnum.PENDING_PAYMENT)
            )) {
                throw new BizIllegalException("订单状态异常");
            }
        }


        // 如果订单完成支付，就需要进行退款操作
        if (order.getPayStatus().equals(PayStatusEnum.SUCCESS)) {
            String result = payService.refund(order.getOrderNo(), order.getTotalPrice().toString());
        }

        // 修改订单状态
        boolean b = lambdaUpdate()
                .eq(SysOrder::getId, order.getId())
                .set(SysOrder::getOrderStatus, isAdmin ? OrderStatusEnum.MERCHANT_CLOSED : OrderStatusEnum.MANUAL_CLOSED)
                .set(SysOrder::getExtraInfo, dto.getExtraInfo())
                .set(SysOrder::getUpdateTime, LocalDateTime.now())
                .update();
        if (!b) throw new DbException("取消订单失败");

    }

    /**
     * 商家发货
     * @param id
     */
    @Override
    public void goodsDelivered(Long id) {
        // 1.更新订单状态
        SysOrder order = getById(id);
        if (order == null) throw new BizIllegalException("订单不存在");
        if (!order.getOrderStatus().equals(OrderStatusEnum.GOODS_ALLOCATED))
            throw new BizIllegalException("订单状态异常");

        boolean b = lambdaUpdate()
                .eq(SysOrder::getId, order.getId())
                .set(SysOrder::getOrderStatus, OrderStatusEnum.GOODS_DELIVERED)
                .set(SysOrder::getUpdateTime, LocalDateTime.now())
                .update();
        if (!b) throw new DbException("出库失败");
    }

    /**
     * 商家配货
     * @param id
     */
    @Override
    @Transactional
    public void goodsAllocated(Long id) {
        // 1. 修改订单状态
        SysOrder order = getById(id);
        if (order == null) throw new BizIllegalException("订单不存在");
        if (!order.getOrderStatus().equals(OrderStatusEnum.PAID)) throw new BizIllegalException("订单状态异常");
        boolean b = lambdaUpdate()
                .eq(SysOrder::getId, order.getId())
                .set(SysOrder::getOrderStatus, OrderStatusEnum.GOODS_ALLOCATED)
                .set(SysOrder::getUpdateTime, LocalDateTime.now())
                .update();
        if (!b) throw new DbException("配货失败");

        // 2. 减少商品数量

        // 2.1 查询出订单项数据
        List<SysOrderItem> orderItems = orderItemService.getOrderItemsByOrderId(order.getId());
        if (CollUtil.isEmpty(orderItems)) throw new BizIllegalException("订单项不存在");
        Map<Long, Integer> goodsMap = orderItems.stream().collect(Collectors.toMap(SysOrderItem::getGoodsId, SysOrderItem::getGoodsCount));

        // 2.2 根据商品id查商品，数量，判断是否可以配送
        List<SysGoodsInfo> goodsInfos = goodsInfoService.lambdaQuery()
                .in(SysGoodsInfo::getId, goodsMap.keySet())
                .list();

        if (CollUtil.isEmpty(goodsInfos)) throw new BizIllegalException("商品不存在");
        for (SysGoodsInfo goodsInfo : goodsInfos) {
            if (goodsInfo.getStockNum() < goodsMap.get(goodsInfo.getId()))
                throw new BizIllegalException("编号为：" + goodsInfo.getId() + "名字：" + goodsInfo.getGoodsName() + "库存不足");
        }

        Long currentId = BaseContext.getCurrentId();
        for (SysGoodsInfo goodsInfo : goodsInfos) {
            goodsInfo.setStockNum(goodsInfo.getStockNum() - goodsMap.get(goodsInfo.getId()));
            goodsInfo.setUpdateUser(currentId);
            goodsInfo.setUpdateTime(LocalDateTime.now());

            // 不需要更新的数据
            goodsInfo.setGoodsCarousel(null);
            goodsInfo.setGoodsDetailContent(null);
            goodsInfo.setTag(null);
            goodsInfo.setGoodsName(null);
            goodsInfo.setGoodsIntro(null);
            goodsInfo.setGoodsCategoryId(null);
            goodsInfo.setGoodsCoverImg(null);
            goodsInfo.setSellingPrice(null);
            goodsInfo.setOriginalPrice(null);
            goodsInfo.setGoodsSellStatus(null);
            goodsInfo.setCreateUser(null);
            goodsInfo.setCreateTime(null);
        }

        // 2.3 减少库存
        goodsInfoService.updateBatchById(goodsInfos);
    }

    @Override
    public OrderDetailsVO getOrderDetail(String orderNo) {
        // 1. 查询订单基础数据
        SysOrder order = getByOrderNo(orderNo);

        OrderDetailsVO vo = BeanUtil.toBean(order, OrderDetailsVO.class);

        // 2. 查询对应的订单项数据
        List<SysOrderItem> orderItems = orderItemService.getOrderItemsByOrderId(order.getId());
        vo.setOrderItemList(orderItems);
        return vo;
    }

    @Override
    public PageDTO<SysOrder> orderQuery(OrderQuery query) {
        Page<SysOrder> page = query.toMpPageDefaultSortByCreateTimeDesc();
        List<Integer> orderStatusList = new ArrayList<>();
        if (query.getOrderStatus() == null || query.getOrderStatus().equals(100)) {
            query.setOrderStatus(null);
        } else if (query.getOrderStatus().equals(200)) {
            orderStatusList.add(OrderStatusEnum.MANUAL_CLOSED.getCode());
            orderStatusList.add(OrderStatusEnum.TIMEOUT_CLOSED.getCode());
            orderStatusList.add(OrderStatusEnum.MERCHANT_CLOSED.getCode());
        } else {
            orderStatusList.add(query.getOrderStatus());
        }
        lambdaQuery()
                .eq(StrUtil.isNotBlank(query.getOrderNo()), SysOrder::getOrderNo, query.getOrderNo())
                .in(!orderStatusList.isEmpty(), SysOrder::getOrderStatus, orderStatusList)
                .between(query.getStartTime() != null && query.getEndTime() != null, SysOrder::getUpdateTime, query.getStartTime(), query.getEndTime())
                .page(page);
        List<SysOrder> records = page.getRecords();
        if (CollUtil.isEmpty(records)) return PageDTO.empty(page);

        return PageDTO.of(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String submitOrder(SubmitOrderDTO dto) {

        Long currentId = BaseContext.getCurrentId();
        BigDecimal totalPrice = new BigDecimal(0);
        List<ShoppingQueryVO> cartItems = new ArrayList<>();
        SysGoodsInfo goodsInfo = new SysGoodsInfo();
        if (dto.getGoodsId() != null && dto.getCartItemIds()== null ){
            // 选择的立即购买，需要查询商品表
            goodsInfo = goodsInfoService.getById(dto.getGoodsId());
            if (goodsInfo == null) throw new BizIllegalException("商品不存在");
            totalPrice = goodsInfo.getSellingPrice();
        }else if (dto.getCartItemIds()!=null && dto.getGoodsId() == null){
            // 查询购物车列表
            // 查询购物信息
            cartItems = shoppingCartItemService.getSelectedItems(dto.getCartItemIds());
            if (CollUtil.isEmpty(cartItems)) throw new BizIllegalException("购物车商品不存在");
            // 统计总价
            totalPrice = cartItems.stream()
                    .map(item -> item.getSellingPrice().multiply(BigDecimal.valueOf(item.getGoodsCount())))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }else {
            throw new BizIllegalException("参数有问题");
        }
        String orderBody = "";
        if (dto.getGoodsId() != null){
            orderBody = goodsInfo.getGoodsName();
        }else {
            orderBody = cartItems.stream().map(ShoppingQueryVO::getGoodsName).collect(Collectors.joining(","));
        }
        //  保存订单
        SysOrder order = saveOrder(currentId, totalPrice,orderBody);

        // 保存订单项
        saveOrderItems(dto, order, goodsInfo, cartItems);

        // 保存订单和地址关系
        saveOrderAndAddress(dto, order, currentId);

        // 删除购物车数据
        if (dto.getCartItemIds()!=null){
            // 删除购物车数据
             shoppingCartItemService.removeByIds(dto.getCartItemIds());
        }

        return order.getOrderNo();
    }

    /**
     * 保存订单和地址关系
     * @param dto
     * @param order
     * @param currentId
     */
    private void saveOrderAndAddress(SubmitOrderDTO dto, SysOrder order, Long currentId) {
        // 保存订单和地址关系
        SysUserAddress userAddress = userAddressService.getUserAddress(dto.getAddressId());
        SysOrderAddress orderAddress = BeanUtil.toBean(userAddress, SysOrderAddress.class);
        orderAddress.setId(null);
        orderAddress.setOrderId(order.getId());
        orderAddress.setUserId(currentId);
        boolean save = orderAddressService.save(orderAddress);
        if (!save) throw new DbException("保存订单地址失败");
    }

    /**
     * 保存订单项信息
     * @param dto
     * @param order
     * @param goodsInfo
     * @param cartItems
     */
    private void saveOrderItems(SubmitOrderDTO dto, SysOrder order, SysGoodsInfo goodsInfo, List<ShoppingQueryVO> cartItems) {
        // 保存购物项信息
        if (dto.getGoodsId() != null ){
            SysOrderItem item = new SysOrderItem();
            item.setOrderId(order.getId());
            item.setGoodsId(goodsInfo.getId());
            item.setGoodsName(goodsInfo.getGoodsName());
            item.setGoodsImage(goodsInfo.getGoodsCoverImg());
            item.setSellingPrice(goodsInfo.getSellingPrice());
            item.setGoodsCount(1);
            orderItemService.save(item);
        }else {
            // 保存订单项
            List<SysOrderItem> sysOrderItems = BeanUtil.copyToList(cartItems, SysOrderItem.class);
            for (SysOrderItem sysOrderItem : sysOrderItems) {
                sysOrderItem.setOrderId(order.getId());
                sysOrderItem.setId(null);
            }
            orderItemService.saveBatch(sysOrderItems);
        }
    }


    /**
     * 保存订单
     * @param currentId
     * @param totalPrice
     * @return
     */
    private SysOrder saveOrder(Long currentId, BigDecimal totalPrice , String orderBody) {
        // 保存订单
        String orderNo = IdUtils.generateOrderNo();
        SysOrder order = new SysOrder();
        order.setOrderNo(orderNo);
        order.setExtraInfo(orderBody);
        order.setUserId(currentId);
        order.setTotalPrice(totalPrice);
        order.setPayStatus(PayStatusEnum.UNPAID);
        order.setOrderStatus(OrderStatusEnum.PENDING_PAYMENT);
        order.setIsDeleted(IsDeletedEnum.NO);
        order.setPayType(PayTypeEnum.NO);
        boolean b = save(order);
        if (!b) throw new DbException("保存订单失败");
        return order;
    }


}
